#include "MyUnit.hpp"

using namespace BWAPI;
using namespace std;

MyUnit::MyUnit(
	BWAPI::Unit* unit
) :	
	m_BWAPIUnit(unit),
	m_state(none),
	m_minCooldown(5)
{
}

void MyUnit::displayLastCommand() const
{
	UnitCommand c = m_BWAPIUnit->getLastCommand();
	UnitCommandType ct = c.getType();
	if (ct == UnitCommandTypes::Attack_Unit) {
		Position p = c.getTarget()->getPosition();
		Broodwar->drawLineMap(m_BWAPIUnit->getPosition().x(), m_BWAPIUnit->getPosition().y(),
			p.x(), p.y(),
			BWAPI::Colors::Red);
	} else if (ct == UnitCommandTypes::Attack_Move) {
		Position p = c.getTargetPosition();
		Broodwar->drawLineMap(m_BWAPIUnit->getPosition().x(), m_BWAPIUnit->getPosition().y(),
			p.x(), p.y(),
			BWAPI::Colors::Red);
	} else if (ct == UnitCommandTypes::Move) {
		Position p = c.getTargetPosition();
		Broodwar->drawLineMap(m_BWAPIUnit->getPosition().x(), m_BWAPIUnit->getPosition().y(),
			p.x(), p.y(),
			BWAPI::Colors::Green);
	}
	displayState();
}

bool MyUnit::targetFire()
{
	const int range = max<int>(16, m_BWAPIUnit->getType().groundWeapon());
	set<Unit*> unitsInRange = m_BWAPIUnit->getUnitsInRadius( range );
	Unit* minHpUnit = NULL;
	int minHP = 10000;
	for (set<Unit*>::const_iterator i=unitsInRange.begin() ; i!=unitsInRange.end() ; i++) {
		if (Broodwar->enemy() == (*i)->getPlayer()
			&& (*i)->getHitPoints()<minHP
			&& (*i)->getHitPoints()>0
			&& (*i)->exists()
		)
		{
			minHP = (*i)->getHitPoints();
			minHpUnit = (*i);
		}
	}
	if (minHpUnit != NULL) {
		// found target - attack it
		m_BWAPIUnit->attack(minHpUnit, false);
		m_state = UnitState::attack;
		return true;
	}
	return false;
}

void MyUnit::onFrameAttack(
	const BWAPI::Position &enemyPosition
)
{
	if ( m_BWAPIUnit->getLastCommand().getType() ==  UnitCommandTypes::Attack_Unit
		&&
			( !m_BWAPIUnit->getLastCommand().getTarget()->exists()
			|| m_BWAPIUnit->getLastCommand().getTarget()->getHitPoints()<=0 )
	)
	{
		// target is no longer valid - stop
		m_BWAPIUnit->stop(false);
		m_state = cooldown;
	}
	if ( m_state == UnitState::attack )
	{
		if ( m_BWAPIUnit->getGroundWeaponCooldown()>m_minCooldown )
		{
			m_state = cooldown;
		}
	}
	if ( m_state == UnitState::cooldown )
	{
		if ( m_BWAPIUnit->getGroundWeaponCooldown()<=m_minCooldown )
		{
			m_state = UnitState::none;
		}
	}
	if ( m_state == UnitState::none )
	{
		if ( !targetFire() )
		{
			m_BWAPIUnit->attack( enemyPosition );
		}
		m_state = UnitState::attack;
	}
}

void MyUnit::displayState() const
{
	BWAPI::Position p = m_BWAPIUnit->getPosition();
	if ( m_state == UnitState::attack ) {
		Broodwar->drawTextMap(p.x(), p.y(), "attack");
	} else if ( m_state == UnitState::none ) {
		Broodwar->drawTextMap(p.x(), p.y(), "none");
	} else if ( m_state == UnitState::cooldown ) {
		Broodwar->drawTextMap(p.x(), p.y(), "cooldown");
	} else if ( m_state == UnitState::reposition ) {
		Broodwar->drawTextMap(p.x(), p.y(), "reposition");
	}
}